﻿using System.Windows.Forms;
using Mbs.ComponentModel.Container;
using Mbs.Globalization;
using Mbs.Windows.Attributes;

namespace Mbs.Windows
{
    /// <summary>
    /// SmartPart 生命周期监听器
    /// </summary>
    public class SmartPartLifecycleListner : ILifecycleListner
    {
        /// <summary>
        /// 监听SmartPart组件被创建
        /// </summary>
        /// <param name="o"></param>
        public void OnCreated(object o)
        {
            var ctr = o as Control;
            if (ctr != null)
                AddControlHierarchy(ctr);
        }

        /// <summary>
        /// 监听SmartPart组件被释放
        /// </summary>
        /// <param name="o"></param>
        public void OnDestroyed(object o)
        {
            var ctr = o as Control;
            if (ctr != null)
                RemoveControlHierarchy(ctr);
        }

        private void AddControlHierarchy(Control control)
        {
            ReplaceIfPlaceHolder(control);

            foreach (Control child in control.Controls)
            {
                if (AddControlToContainer(child) == false)
                    AddControlHierarchy(child);
            }
        }

        private void RemoveControlHierarchy(Control control)
        {
            if (control != null)
                RemoveNestedControls(control);
        }

        private bool AddControlToContainer(Control control)
        {
            if (ShouldAddControlToContainer(control))
            {
                if (control.Name.Length != 0)
                    ExtensionLocator.Register(control.Name, control);
                else
                    ExtensionLocator.Register(control.GetHashCode().ToString(), control);

                return true;
            }

            return false;
        }

        private bool ShouldAddControlToContainer(Control control)
        {
            return !ExtensionLocator.ContainsObject(control)
                && (
                    IsSmartPart(control) 
                    || IsWorkspace(control) 
                    || IsPlaceholder(control));
        }

        private bool IsPlaceholder(Control control)
        {
            return (control is ISmartPartPlaceHolder);
        }

        private bool IsSmartPart(Control control)
        {
            return (control.GetType().GetCustomAttributes(typeof(SmartPartAttribute), true).Length > 0)
                || control is ISmartPartView;
        }

        private bool IsWorkspace(Control control)
        {
            return (control is IWorkspace);
        }

        private void RemoveNestedControls(Control control)
        {
            foreach (Control child in control.Controls)
            {
                ExtensionLocator.Remove(child);
                RemoveNestedControls(child);
            }
        }

        private void ReplaceIfPlaceHolder(Control control)
        {
            ISmartPartPlaceHolder placeholder = control as ISmartPartPlaceHolder;

            if (placeholder != null)
            {
                Control replacement = ExtensionLocator.Get<Control>(placeholder.SmartPartName);

                if (replacement != null)
                    placeholder.SmartPart = replacement;
            }
        }
    }

    public class SmartPartKernelListner : Mbs.ComponentModel.Container.Listner.KernelListnerAdapter
    {
        private SmartPartLifecycleListner InnerListner = new SmartPartLifecycleListner();
        LanguageChangedLifecycleListner languageListner = new LanguageChangedLifecycleListner();
        public SmartPartKernelListner() : base(Mbs.ComponentModel.Container.Listner.LifestyleStage.Created | Mbs.ComponentModel.Container.Listner.LifestyleStage.Destroyed) { }

        public override void OnCreated(Mbs.ComponentModel.Container.Metadata.IComponentInfo info, object instance)
        {
            InnerListner.OnCreated(instance);
            languageListner.OnCreated(instance);
        }

        public override void OnDestroyed(Mbs.ComponentModel.Container.Metadata.IComponentInfo info, object instance)
        {
            InnerListner.OnDestroyed(instance);
            languageListner.OnDestroyed(instance);
        }
    }
}
